

#include "cybertron/network/NetworkActionExecuter.hpp"
#include "cybertron/network/NetworkActionLambda.hpp"

CYBERTRON_BEGIN

CybertronCoreAPI NetworkActionExecuter::NetworkActionExecuter()
{
	zeroMembers();
}

CybertronCoreAPI NetworkActionExecuter::~NetworkActionExecuter()
{
	clear();
}

void NetworkActionExecuter::zeroMembers()
{
	//mMillisecondsTimeout = 5 * 1000;
	mMillisecondsTimeout = -1;
}

CybertronCoreAPI void NetworkActionExecuter::initialize(
	std::shared_ptr<SocketBase> pSocket,
	int millisecondsTimeout)
{
	clear();

	mpSocket = pSocket;
	mMillisecondsTimeout = millisecondsTimeout;
}

std::shared_ptr<NetworkActionBase> NetworkActionExecuter::getActiveAction()
{
	auto pAction = mpCurrentAction;
	while (pAction == nullptr || pAction->getEnded())
	{
		if (mActions.size() == 0)
		{
			mpCurrentAction = nullptr;
			return nullptr;
		}

		mpCurrentAction = mActions.front();
		mActions.pop_front();
		pAction = mpCurrentAction;

		pAction->setStart();
		if (!pAction->getEnded())
		{
			return pAction;
		}

		mpCurrentAction = nullptr;
	}

	return pAction;
}

CybertronCoreAPI void NetworkActionExecuter::onTimer(int ms)
{
	auto pAction = getActiveAction();
	if (pAction == nullptr)
	{
		return;
	}

	pAction->handleTimer(ms);
}

CybertronCoreAPI void NetworkActionExecuter::onMessage(Message& msg)
{
	auto pAction = getActiveAction();
	if (pAction == nullptr)
	{
		return;
	}

	pAction->handleMessage(msg);
}

CybertronCoreAPI void NetworkActionExecuter::clear()
{
	auto pAction = mpCurrentAction;
	mpCurrentAction = nullptr;

	if (pAction != nullptr)
	{
		pAction->setEnd();
		pAction = nullptr;
	}

	mActions.clear();

	mpSocket.reset();

	zeroMembers();
}

CybertronCoreAPI void NetworkActionExecuter::queueAction(
	std::uint16_t desiredMsgId,
	std::shared_ptr<NetworkActionBase> pAction, 
	int timeoutMilliseconds)
{
	if (pAction == nullptr)
	{
		return;
	}

	pAction->setSocket(mpSocket.lock());
	pAction->setDesiredMessageId(desiredMsgId);
	pAction->setTimeout(timeoutMilliseconds);

	mActions.push_back(pAction);
}

CybertronCoreAPI void NetworkActionExecuter::queueAction(
	std::uint16_t desiredMsgId,
	std::shared_ptr<NetworkActionBase> pAction)
{
	if (pAction == nullptr)
	{
		return;
	}

	pAction->setSocket(mpSocket.lock());
	pAction->setDesiredMessageId(desiredMsgId);
	//pAction->setTimeout(mMillisecondsTimeout);

	mActions.push_back(pAction);
}

CybertronCoreAPI void NetworkActionExecuter::queueAction(
	std::uint16_t desiredMsgId,
	std::function<void()> funcOnStart,
	std::function<void(Message&)> funcOnDesiredMessage,
	std::function<void()> funcOnTimeout)
{
	std::shared_ptr<NetworkActionLambda> pAction = std::make_shared<NetworkActionLambda>();
	pAction->setFuncOnStart(funcOnStart);
	pAction->setFuncOnDesiredMessage(funcOnDesiredMessage);
	pAction->setFuncOnTimeout(funcOnTimeout);

	queueAction(desiredMsgId, pAction);
}

CybertronCoreAPI bool NetworkActionExecuter::isBusy() const
{
	if (mpCurrentAction != nullptr)
	{
		return true;
	}
	if (mActions.size() > 0)
	{
		return true;
	}

	return false;
}

CYBERTRON_END
